﻿using System;
using System.Collections.Generic;
using System.Configuration;
using Less.Core;
using Less.Core.Model;

namespace Less.DAL
{
    /// <summary>
    /// Data Access Layer to work with Users Records
    /// </summary>
    internal class UsersDAL : GenericDAL<User>
    {
        public string SQLSelectUsersByRoleName
        {
            get
            {
                string name = ConfigurationManager.AppSettings["UsersDAL.SelectUsersByRoleNameSQL"];
                if (name == null)
                {
                    name = "SELECT u.* FROM Users u INNER JOIN UsersRoles ur ON u.Id = ur.UserId INNER JOIN Roles r ON r.Id = ur.RoleId WHERE r.Name = @0  ";
                }
                return name;
            }
        }
        
        internal UsersDAL(IDatabase database)
        : base(database,"Users")
        {
        }

        internal UsersDAL()
        : base(new Database(LessDatabaseUtils.LessConnectionStringName),"Users")
        {
            
        }

        /// <summary>
        /// Gets all the User Records related with a Role of a given name
        /// </summary>
        /// <param name="roleName">The name of the role</param>
        /// <returns></returns>
        public List<User> SelectUsersByRoleName(string roleName)
        {
            List<User> list = null;
            list = Database.SelectList<User>(SQLSelectUsersByRoleName, roleName);
            return list;
        }

        public int GetNumberOfUsersOnline(DateTime dateLastActivity)
        {
            int num = 0;
            num = Database.ExecuteScalar<int>(string.Format("SELECT COUNT(Id) FROM {0} WHERE DateLastActivity > @0", TableName), dateLastActivity);
            return num;
        }

        /// <summary>
        /// Gets a User Record 
        /// </summary>
        /// <param name="userName">The User userName</param>
        /// <returns>The User Record </returns>
        public User SelectByName(string userName)
        {
            User record = null;
            record = Database.Select<User>(string.Format("SELECT * FROM {0} WHERE UserName=@0",  TableName), userName);
            return record;
        }

        /// <summary>
        /// Gets a User Record 
        /// </summary>
        /// <param name="email">The User Email</param>
        /// <returns>The User Record </returns>
        public User SelectByEmail(string email)
        {
            User record = null;
            record = Database.Select<User>(string.Format("SELECT * FROM {0} WHERE Email=@0",  TableName), email);
            return record;
        }

        /// <summary>
        /// Gets a User Record 
        /// </summary>
        /// <param name="identifier">The User identifier</param>
        /// <returns>The User Record </returns>
        public User SelectByIdentifier(string identifier)
        {
            User record = null;
            record = Database.Select<User>("SELECT u.* FROM Users u INNER JOIN Identifiers i on u.Id = i.UserId WHERE i.GUID=@0",identifier);
            return record;
        }
        /// <summary>
        /// Gets the password stored for a user, checked with then answer of a secret question
        /// </summary>
        /// <param name="username"></param>
        /// <param name="answer"></param>
        /// <returns></returns>
        public string GetPassword(string username, string answer)
        {
            string password = null;
            password = Database.ExecuteScalar<string>("SELECT Password FROM Users WHERE UserName = @0 AND IsApproved = 1", username);
            return password;
        }

        

        public override List<string> Validate(object record)
        {
            List<string> brokenRules = new List<string>();
            User user = record as User;
            if ( user.CreationDate == DateTime.MinValue) user.CreationDate = DateTime.Now;
            if ( user.FailedPasswordAttemptWindowStart == DateTime.MinValue ) user.FailedPasswordAttemptWindowStart = LessDatabaseUtils.SqlDateMinValue;
            if ( user.FailedPasswordAnswerAttemptWindowStart == DateTime.MinValue ) user.FailedPasswordAnswerAttemptWindowStart = LessDatabaseUtils.SqlDateMinValue;
            if ( user.LastActivityDate == DateTime.MinValue ) user.LastActivityDate = LessDatabaseUtils.SqlDateMinValue;
            if ( user.LastLockoutDate == DateTime.MinValue ) user.LastLockoutDate = LessDatabaseUtils.SqlDateMinValue;
            if ( user.LastLoginDate == DateTime.MinValue ) user.LastLoginDate = LessDatabaseUtils.SqlDateMinValue;
            if ( user.LastPasswordChangedDate == DateTime.MinValue ) user.LastPasswordChangedDate = LessDatabaseUtils.SqlDateMinValue;
            if (user.Password.IsNullOrEmpty())                 user.Password = user.UserName;
            user.Password = user.Password.Left(20);
            if (user.UserName.IsNullOrEmpty())
            {
                brokenRules.Add("UserName must have a value");
            }
            return brokenRules;
        }
    }
}